package org.delphy.indy2.containers
{
	import caurina.transitions.Tweener;
	
	import com.roguedevelopment.pulse.PulseEngine;
	import com.roguedevelopment.pulse.emitter.BitmapEmitter;
	import com.roguedevelopment.pulse.simple.SimpleParticles;
	
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.TimerEvent;
	import flash.filters.ColorMatrixFilter;
	import flash.geom.Point;
	import flash.utils.Timer;
	
	import mx.containers.Canvas;
	import mx.controls.Image;
	import mx.events.FlexMouseEvent;
	import mx.managers.PopUpManager;
	
	import org.delphy.indy2.containers.carbonFireworksBoxClasses.*;

	public class CarbonFireworksBox extends Canvas
	{
		//--------------------------------------
		//  Emitter and animation
		//--------------------------------------
		
		/**
		 * @public
		 */
		[Embed(source="org/delphy/indy2/assets/images/particle.png")] 
		[Bindable]
		public var spark:Class;
				
		/**
		 * @protected
		 */
		protected var emitter:BitmapEmitter

		/**
		 * @protected
		 */
		protected var canvasSprite:Sprite;
		
		/**
		 * @protected
		 */		
		protected var firstParticle:Image;
		
		/**
		 * @public
		 * 
		 * @default 1.5
		 */		
		[Bindable]
		public var lifeSpan:Number=1.5;		
		
		/**
		 * @public
		 * 
		 * @default 1.5
		 */				
		[Bindable]
		public var risingTime:Number=1.5;

		/**
		 * @public
		 * 
		 * @default 30
		 */		
		[Bindable]
		public var numParticles:Number=30;

		/**
		 * @public
		 * The y position where we play "explode" animation
		 * 
		 * @default 100
		 */		
		[Bindable]
		public var explodeY:Number=100;
		
		/**
		 * @public
		 * 
		 * @default 2
		 */				
		[Bindable]
		public var transitionTime:Number=2;

		//--------------------------------------
		//  Host
		//--------------------------------------
		
		/**
		 * @protected
		 */
		protected var hostY:Number;
		
		/**
		 * @public
		 * The host object
		 */
		protected var _host:DisplayObject=null;
		public function get host():DisplayObject
		{ 
			return _host; 
		}

		public function set host(value:DisplayObject):void
		{
			if (value !== _host)
			{
				_host = value;
			}
		}

		//--------------------------------------
		//  Methods
		//--------------------------------------
		
		/**
		 * Constructor
		 */
		public function CarbonFireworksBox()
		{
			super();
			
			clipContent=false;
			
			addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE,close);									
			
			canvasSprite=new Sprite();
			rawChildren.addChild(canvasSprite);
		}
		
		/**
		 * @protected
		 */
		protected function generateColorFilter():ColorMatrixFilter{
			
			var matrix:Array=[0, 0, 0, 0, 0,
		  		    		  0, Math.random(), 0, 0, 0,
		 					  0, 0, Math.random(), 0, 0,
							  0, 0, 0, 1, 0];
			
			var colorMatrixFilter:ColorMatrixFilter=new ColorMatrixFilter(matrix);
			
			return colorMatrixFilter;
		}

		/**
		 * @public
		 */
		public function popUp():void{
			if(_host==null)
				_host=parent;
			
			// Because we are using PopUpManager to popup the fireworks, we need to make
			// sure that the CarbonFireworksBox been removed from its parent container.
			if(parent)
				parent.removeChild(this);
			
			var hostCenter:Point=new Point(_host.x,_host.y);
			hostCenter=_host.parent.localToGlobal(hostCenter);
			
			x=hostCenter.x+ (_host.width-this.width)/2;
			y=hostCenter.y-this.height;
			
			for(var i:uint=0;i<numChildren;i++){
				var child:DisplayObject=getChildAt(i);
				child.x=width/2;
				child.y=explodeY/2;
				child.alpha=0;				
			}
			
			PopUpManager.addPopUp(this,_host,false);
			
			fire();
		}

		/**
		 * @protected
		 */
		protected function fire():void{
			firstParticle=new Image();
			firstParticle.source=spark;
		
			firstParticle.width=24;
			firstParticle.height=24;
		
			firstParticle.x=width/2-firstParticle.width/2;
			firstParticle.y=height;
			
			rawChildren.addChild(firstParticle);
						
			doTrackAnimation();
		}
		
		/**
		 * @protected
		 */		
		protected function doTrackAnimation():void{
			Tweener.addTween(firstParticle,{y:explodeY,alpha:0,time:risingTime,transition:"linear", 
							onComplete:explode, onUpdate:onTrackAnimationUpdate});
		}
		
		/**
		 * @protected
		 */
		protected function onTrackAnimationUpdate():void{
		}
		
		/**
		 * @protected
		 */		
		protected function explode(evt:Event=null):void{
			Tweener.removeTweens(firstParticle);
			rawChildren.removeChild(firstParticle);
			
			PulseEngine.instance.root = canvasSprite;
			var bmd:BitmapData = new BitmapData(width,height, true, 0 );
			var bm:Bitmap = new Bitmap(bmd);
			canvasSprite.addChild(bm);		
				
			emitter = new CarbonBitmapEmitter(numParticles, bmd ,0.9);
			SimpleParticles.configureEmitterByObject(emitter, 
													 {x:0, y:0, 
													  width:1, height:1,
													  image:spark, 
													  movement:true,
													  minSpeed:100, maxSpeed:300, 
													  accel:-10,
													  gravity:9.8,
													  fade:20*Math.random(),
													  scale:[lifeSpan*1000,1,0],
													  minAngle:0, maxAngle:360, 
													  minScale:0.4, maxScale:0.75,  
													  lifespan:lifeSpan*1000} );			
			emitter.root.x = width/2;
			emitter.root.y = explodeY;
			
			var timer:Timer=new Timer(lifeSpan*1000,1);
			timer.start();
			timer.addEventListener(TimerEvent.TIMER,removeParticles);			
		}
		
		/**
		 * @protected
		 */		
		protected function removeParticles(evt:Event=null):void{
			emitter.stop();

			arrangeChildren();
		}		

		/**
		 * @protected
		 */
		protected function arrangeChildren():void{
			for(var i:uint=0;i<numChildren;i++){
				var angle:Number=-Math.PI + Math.PI*2/numChildren*i;
				var childPosition:Point=getPointAt(angle);
				var child:DisplayObject=getChildAt(i);
				
				childPosition.x=childPosition.x-child.width;
				if(childPosition.x<0)
					childPosition.x=0;
				else if(childPosition.x+child.width>width)
					childPosition.x=width-child.width;
				

				childPosition.y=childPosition.y-child.height;
				if(childPosition.y<0)
					childPosition.y=0;
				else if(childPosition.y+child.height>height)
					childPosition.y=height-child.height;
				
				Tweener.addTween(child,{x:childPosition.x,y:childPosition.y,alpha:1,time:transitionTime});				
			}		
		}
		
		/**
		 * @public
		 */
		public function close(evt:Event=null):void{
			PopUpManager.removePopUp(this);
		}

		/**
		 * @protected
		 */
		protected function getPointAt(angle:Number):Point{
			var pt:Point=new Point();
			pt.x=width/2 * Math.cos(angle)+width/2;
			pt.y=width/2 * Math.sin(angle)+width/2;
			
			return pt;
		}
		
		/**
		 * @protected
		 */
		override protected function createChildren() : void{
			super.createChildren();
			
			// Hide all children
			for(var i:uint=0;i<numChildren;i++){
				var child:DisplayObject=getChildAt(i);
				child.alpha=0;
			}
		}
	}
}